#include "stdlib.hpp"
#include <purewell/types.hpp>
#include <purewell/pipe.hpp>
#include <purewell/system.hpp>

namespace purewell
{

PWPipe::PWPipe()
{
}

PWPipe::~PWPipe()
{
}

ssize_t
PWPipe::write(const void* buf, size_t blen)
{
	return ::write(m_fd2, (const char*)buf, blen);
}

ssize_t
PWPipe::read(void* buf, size_t blen)
{
	return ::read(m_fd, (char*)buf, blen);
}

bool
PWPipe::initialize(void)
{
	int fd[2];
	if ( 0 != pipe(fd) ) return false;

	if ( !attach2(fd) )
	{
		::close(fd[0]);
		::close(fd[1]);
		return false;
	}

	return true;
}

PWNamedPipe::PWNamedPipe()
{
}

PWNamedPipe::~PWNamedPipe()
{
}

bool
PWNamedPipe::initialize(const char* name, int flag, int perm)
{
	std::string _name;
	PWSystem::getInstance().getCurrentDirectory(_name);
	if ( _name.empty() ) return false;
	_name.append(PWDIR_DELIMITER);
	_name.append(name);

	int nflag(flag & ~(O_CREAT|O_EXCL));
	int fd(open(name, nflag, perm));

	if ( -1 == fd )
	{
		if ( flag & O_CREAT )
		{
			if ( 0 != mkfifo(name, perm) )
			{
				return false;
			}

			if ( -1 == (fd = open(name, nflag, perm)) )
			{
				::unlink(name);
				return false;
			}

			m_fd = fd;
			m_name.swap(_name);
			return true;
		}

		return false;
	}

	if ( flag & O_EXCL )
	{
		::close(fd);
		return false;
	}

	struct stat stat;
	if ( 0 != fstat(fd, &stat) )
	{
		::close(fd);
		return false;
	}

	if ( !S_ISFIFO(stat.st_mode) )
	{
		::close(fd);
		return false;
	}

	m_fd = fd;
	m_name.swap(_name);

	return true;
}


};//namespace purewell

